﻿/**
 *       Project: ServerLib
 *     Copyright: Copyright (C) 2008, Rob Kennedy
 *   Create Date: 2008-14-07 4:43 PM
 * Modified Date: 2008-14-07 4:43 PM    RK  Added comments
 *      Comments: Ignore SA1633.
 *      
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

namespace ServerLib.Core
{
    using System;
    using System.IO;
    using System.Linq;
    using System.Data.Linq;
    using ServerLib.Data;
using ServerLib.Security;

    /// --------------------------------------------------------------------
    /// Project	 : ServerLib
    /// Class	 : Logging
    /// Inherits : IDisposable
    /// --------------------------------------------------------------------
    /// <summary>
    ///  Contains the primary static interface for logging information to
    ///  a log file for a particular service.
    /// </summary>
    /// <authorname>Rob Kennedy</authorname>
    /// <remarks>
    ///     May need rewrite to use alternative logging methods (xml/events/etc)
    /// </remarks>
    /// --------------------------------------------------------------------
    public class Logging : IDisposable
    {
        #region Public Enumerations

        /// <summary>
        /// Logging Event Types for database logging
        /// </summary>
        public enum LoggingEventTypes
        {
            /// <summary>General messages are non-error related</summary>
            GeneralMessage,

            /// <summary>General errors are service specific</summary>
            GeneralError,

            /// <summary>System errors are application exceptions</summary>
            SystemError
        }

        #endregion

        #region Private Properties

        /// <summary>Contains a database connection object</summary>
        private static IDatabase dataConnection;

        /// <summary>Holds the current log file name</summary>
        private static string logFileName;

        /// <summary>Holds the current log stream writer</summary>
        private static StreamWriter logFileWriter;

        /// <summary>Hods the service name</summary>
        private static string serviceName = string.Empty;

        /// <summary>Holds the current logging path</summary>
        private static string loggingPath = string.Empty;

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the database connection object
        /// </summary>
        public static IDatabase DataConnection
        {
            get
            {
                return dataConnection;
            }

            set
            {
                dataConnection = value;
            }
        }

        /// <summary>
        /// Gets the log file path name to write all log events to
        /// </summary>
        public static string LogFileName
        {
            get
            {
                return logFileName;
            }
        }

        /// <summary>
        /// Gets or sets the log file stream writer object
        /// </summary>
        public static StreamWriter LogFileWriter
        {
            get
            {
                return logFileWriter;
            }

            set
            {
                logFileWriter = value;
            }
        }

        /// <summary>
        /// Gets or sets the Service name this log is written for. This name will
        /// be prefixed to the log file name if set.
        /// </summary>
        public static string ServiceName
        {
            get
            {
                return serviceName;
            }

            set
            {
                serviceName = value;
            }
        }

        /// <summary>
        /// Gets or sets the path that log files are stored. This will be used when 
        /// auto-generating a log file name.
        /// </summary>
        public static string LoggingPath
        {
            get
            {
                return loggingPath;
            }

            set
            {
                loggingPath = value;
            }
        }

        #endregion

        #region Public Constructors

        /// <summary>
        /// Creates a new Logging class
        /// </summary>
        /// <remarks>
        /// Ignore SA1201
        /// </remarks>
        public Logging()
            : this(string.Empty) 
        { 
        }

        /// <summary>
        /// Creates a new Logging class with service name specified.
        /// </summary>
        /// <param name="serviceName">The name of the service to log for.</param>
        /// <remarks>Ignore SA1201</remarks>
        public Logging(string serviceName)
        {
            ServiceName = serviceName;
        }

        #endregion

        #region Public Properties

        /// <summary>
        ///  Writes a specified message to the current log file
        /// </summary>
        /// <param name="message">Message to write to the current log file</param>
        public static void WriteLog(string message)
        {
            //WriteLog(message, false, false, false);
        }

        /// <summary>
        ///  Writes a specified message to the current log file
        /// </summary>
        /// <param name="message">Message to write to the current log file</param>
        /// <param name="logDate">
        /// If true, prefixes the current date and time to the Message line 
        /// when written to the current log file.
        /// </param>
        public static void WriteLog(string message, bool logDate)
        {
            //WriteLog(message, logDate, false, false);
        }

        /// <summary>
        ///  Writes a specified message to the current log file
        /// </summary>
        /// <param name="message">Message to write to the current log file</param>
        /// <param name="logDate">
        /// If true, prefixes the current date and time to the Message line 
        /// when written to the current log file.
        /// </param>
        /// <param name="logHorizontalRule">
        /// If true, prefixes a horizontal rule line before the message line
        /// when written to the current log file.
        /// </param>
        public static void WriteLog(string message, bool logDate, bool logHorizontalRule)
        {
            //WriteLog(message, logDate, logHorizontalRule, false);
        }

        /// <summary>
        ///  Writes a specified message to the current log file
        /// </summary>
        /// <param name="message">Message to write to the current log file</param>
        /// <param name="logDate">
        /// If true, prefixes the current date and time to the Message line 
        /// when written to the current log file.
        /// </param>
        /// <param name="logHorizontalRule">
        /// If true, prefixes a horizontal rule line before the message line
        /// when written to the current log file.
        /// </param>
        /// <param name="consoleDisplay">
        /// If true, renders the message line to the terminal Console for debugging.
        /// </param>
        public static void WriteLog(string message, bool logDate, bool logHorizontalRule, bool consoleDisplay, LoggingEventTypes loggingEventType)
        {
            // if our logging path is not defined, define one
            if (loggingPath.Length == 0)
            {
                loggingPath = Paths.AppendSlash(Paths.AppPath) + "Logs";
            }

            // build a complete path to a log file using the current date
            // this will allow log files to roll over into a new file after
            // midnight; creating a log file per day. 
            // TODO: add ability to change the log file interval.
            logFileName = string.Format("{0}\\{1}_{2:MM-dd-yyyy}.txt", loggingPath, serviceName, DateTime.Now);
        
            try
            {
                logFileWriter = new StreamWriter(new FileStream(logFileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite));

                if (logFileWriter != null)
                {
                    // lock the stream writer from other threads while we're using it.
                    lock (logFileWriter)
                    {
                        // if we are writting the HR...
                        if (logHorizontalRule)
                        {
                            logFileWriter.WriteLine("----");
                            if (consoleDisplay)
                            {
                                Console.WriteLine("----");
                            }
                        }

                        // if we are prefixing date/time...
                        if (logDate)
                        {
                            // TODO: {0:u} is universal date format, we may want to modify this or give option to.
                            logFileWriter.Write("{0:u} ", DateTime.Now);
                            if (consoleDisplay)
                            {
                                Console.Write("{0:u} ", DateTime.Now);
                            }
                        }

                        logFileWriter.WriteLine(message);

                        if (consoleDisplay)
                        {
                            Console.WriteLine(message);
                        }
                    }
                }
                
            }
            catch (IOException iex)
            {
                // TODO: Determine how to log this error other than console
                Console.WriteLine("Error: Logging; {0}", iex.Message);
            }
            catch (Exception ex)
            {
                // TODO: Determine how to log this error other than console
                Console.WriteLine("Error: Unable to access file {0}; {1}", logFileName, ex);
            }
            finally
            {
                // finally close log stream
                Close();
            }
        }

        public static void WriteLog(IDatabase dataConnection, LoggingEventTypes loggingEventType, UserAccount user, int eventCode, string eventMessage, bool consoleDisplay)
        {
            if (dataConnection != null)
            {
                bool wasPreviouslyConnected = DataConnection.IsConnected;

                if (!wasPreviouslyConnected)
                {
                    dataConnection.Open();
                }

                if (dataConnection.IsConnected)
                {
                    
                }

                // if we weren't previously connected, then close, otherwise leave open
                if (!wasPreviouslyConnected && dataConnection.IsConnected)
                {
                    dataConnection.Close();
                }
            }
        }

        /// <summary>
        ///  Closes an open log file writer stream if any exists.
        /// </summary>
        public static void Close()
        {
            if (logFileWriter != null)
            {
                lock (logFileWriter)
                {
                    logFileWriter.Close();
                }
            }
        }
        
        /// <summary>
        ///  Dispose of current object members
        /// </summary>
        public void Dispose()
        {
            if (logFileWriter != null)
            {
                lock (logFileWriter)
                {
                    logFileWriter.Close();
                    logFileWriter.Dispose();
                }
            }
        }

        #endregion
    }
}
